package me.mononin.common.common.widget.recycler;

import android.support.annotation.LayoutRes;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import butterknife.ButterKnife;
import butterknife.Unbinder;
import me.mononin.common.R;

/**
 * RecyclerView适配器的封装
 *
 * @author  mononing on 18-2-24.
 */

public abstract class RecyclerAdapter<Data> extends
        RecyclerView.Adapter<RecyclerAdapter.ViewHolder<Data>>implements
        View.OnClickListener,View.OnLongClickListener
        ,AdapterCallback<Data>{

    private final List<Data> mDataList;
    private AdapterListener listener;

    /**
     * 设置无参构造器
     */
    public RecyclerAdapter(){
        this(null);
    }

    /**
     * 单个参数构造器
     * @param listener 监听器
     */
    public RecyclerAdapter(AdapterListener<Data> listener){
        this(new ArrayList<Data>(),listener);
    }

    /**
     * 双参构造器
     * @param list 数据集合
     * @param listener 监听器
     */
    public RecyclerAdapter(List<Data> list,AdapterListener<Data> listener){
        this.mDataList = list;
        this.listener = listener;
    }


    /**
     * 创建一个viewHolder
     * @param parent 父布局
     * @param viewType 约定为自定义的布局ID
     * @return 返回一个viewHolder
     */
    @Override
    public ViewHolder<Data> onCreateViewHolder(ViewGroup parent, int viewType) {
        //获取自定义布局View，从而生成一个ViewHolder
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(viewType,parent,false);
        //通过子类必须实现来生成一个ViewHolder
        ViewHolder holder = onCreateViewHolder(view,viewType);

        //对于点击事件发生View和其ViewHolder进行绑定，以便之后获取对应ViewHolder
        view.setTag(R.id.recycler_adapter_holder,holder);

        //点击和长按事件
        view.setOnClickListener(this);
        view.setOnLongClickListener(this);


        holder.unbinder = ButterKnife.bind(holder,view);
        holder.callback = this;
        return holder;
    }

    /**
     * 强制子类必须实现从而生成一个可用的ViewHolder
     * @param view
     * @param viewType
     * @return
     */
    protected abstract ViewHolder<Data> onCreateViewHolder(View view,int viewType);

    /**
     * 绑定viewHolder
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(ViewHolder<Data> holder, int position) {
        Data data = mDataList.get(position);
        //实际进行绑定操作
        holder.bind(data);
    }

    /**
     * 获取数据个数
     * @return 返回数据个数
     */
    @Override
    public int getItemCount() {
        return mDataList.size();
    }


    /**
     * 获取当前选中视图View的类型
     * @param position 当前选中视图位置position
     * @return  类型，返回XML资源ID
     */
    @Override
    public int getItemViewType(int position) {
        return getItemViewType(position,mDataList.get(position));
    }

    /**
     * 得到布局类型
     * @param position 位置position
     * @param data 当前数据
     * @return 返回XML资源ID
     */
    @LayoutRes
    protected abstract int getItemViewType(int position,Data data);

    /**
     * 添加一个范型数据并通知更新
     * @param data 范型
     */
    public void add(Data data){
        mDataList.add(data);
        notifyItemChanged(mDataList.size()-1);
    }

    /**
     * 添加一个范型数组并通知更新
     * @param dataList 范型数组
     */
    public void add(Data... dataList){
        if(dataList!=null&&dataList.length>0){
            int startPos = mDataList.size();
            Collections.addAll(mDataList,dataList);
            notifyItemRangeChanged(startPos,dataList.length);
        }
    }

    /**
     * 添加一个范型集合并通知更新
     * @param dataList
     */
    public void add(Collection<Data> dataList){
        if (dataList!=null&&dataList.size()>0){
            int startPos = mDataList.size();
            mDataList.addAll(dataList);
            notifyItemRangeChanged(startPos,dataList.size());
        }
    }

    /**
     * 清空数据
     */
    public void clear(){
        mDataList.clear();
        notifyDataSetChanged();
    }

    /**
     * 替换了整个集合，包含清空
     * @param dataList 范型集合
     */
    public void replace(Collection<Data> dataList){
        mDataList.clear();
        if (dataList!=null&&dataList.size()>0){
            mDataList.addAll(dataList);
            notifyDataSetChanged();
        }else {
            return;
        }
    }

    @Override
    public void update(Data data, ViewHolder<Data> holder) {
        //获取当前holder的坐标
        int pos = holder.getAdapterPosition();
        //更新信息
        if (pos>=0){
            mDataList.remove(pos);
            mDataList.add(pos,data);
            //通知进行更新
            notifyItemChanged(pos);
        }

    }

    @Override
    public void onClick(View view) {
        //通过getTag获取ViewHolder
        ViewHolder viewHolder = (ViewHolder) view.getTag(R.id.recycler_adapter_holder);

        if (listener!=null){
            //获取viewHolder所在的坐标
            int pos = viewHolder.getAdapterPosition();
            //设置监听回调
            listener.onItemClick(viewHolder,mDataList.get(pos));
        }

    }

    @Override
    public boolean onLongClick(View view) {
        //通过getTag获取ViewHolder
        ViewHolder viewHolder = (ViewHolder) view.getTag(R.id.recycler_adapter_holder);

        if (listener!=null){
            //获取viewHolder所在的坐标
            int pos = viewHolder.getAdapterPosition();
            //设置监听回调
            listener.onItemLongClick(viewHolder,mDataList.get(pos));
            return true;
        }

        return true;
    }

    /**
     * 自定义点击监听器
     * @param <Data> 范型
     */
    public interface AdapterListener<Data>{
        //当用户点击时触发
        void onItemClick(RecyclerAdapter.ViewHolder holder,Data data);

        //当用户长按时触发
        void onItemLongClick(RecyclerAdapter.ViewHolder holder,Data data);
    }

    /**
     * 返回整个集合
     *
     * @return List<Data>
     */
    public List<Data> getItems() {
        return mDataList;
    }

    /**
     * 设置监听器
     * @param listener
     */
    public void setListener(AdapterListener<Data> listener){
        this.listener = listener;
    }

    /**
     * 自定义的ViewHolder
     * @param <Data> 范型
     */
    public abstract static class ViewHolder<Data> extends RecyclerView.ViewHolder{
        protected Data mData;
        private Unbinder unbinder;
        private AdapterCallback callback;
        public ViewHolder(View itemView) {
            super(itemView);
        }

        /**
         * 用于绑定数据的触发
         * @param data
         */
        void bind(Data data){
            this.mData = data;
            onBind(data);
        }

        /**
         * 具体实现数据绑定操作，必须在子类当中覆写
         * @param data
         */
        protected abstract void onBind(Data data);

        /**
         * 自己对自己的数据进行更新操作
         * 数据更新操作
         * @param data
         */
        public void updateBind(Data data){
            if (this.callback!=null){
                this.callback.update(data,this);
            }
        }

    }

    /**
     * 实现一个静态抽象Adapter监听类
     *
     * 目的是能够使外部监听类只实现单一的监听操作
     * @param <Data>
     */
    public static abstract class AdapterListenerImpl<Data> implements AdapterListener<Data>{

        @Override
        public void onItemClick(RecyclerAdapter.ViewHolder holder, Data data) {

        }

        @Override
        public void onItemLongClick(RecyclerAdapter.ViewHolder holder, Data data) {

        }
    }
}
